/*
 * @Author: 0x9DEFA478
 * @Date: 2024-07-21 19:28:55
 * @LastEditTime: 2024-09-22 20:15:17
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#include "./H_TS_LL.h"
#include "./H_TS_LL_Memory.h"




extern void (*volatile H_TS_LL_ThreadScheduleISR)(void);
extern void H_TS_LL_StartFirstThread(void);




static void* Malloc(Hsize Size);
static void Free(void* v);
static void TypeCheck(void);




static int delete_H_TS_Thread(H_TS_Thread* Thread){
  Hsize Status;
  int H_TS_IsStart;

  Status=Thread->Status;
  if(Status!=vH_TS_Thread_Status_Stop){
    return -1;
  }

  if(H_TS_LL_Core_Instance.CurrentThread==NULL){
    H_TS_IsStart=0;
  }else{
    H_TS_IsStart=-1;

    oH_TS_LL_SchedulerSuspend();//挂起线程调度
  }

  H_TS_LL_Core_Instance.Memory.Free(Thread);

  if(H_TS_IsStart!=0){
    oH_TS_LL_ResumeSchedulerAuto();//允许线程调度
  }

  return 0;
}

static int H_TS_IdleProcess(void* v){
  void (*IdleProcess)(void*);
  H_TS_Thread* p;
  H_TS_Thread* p_Add;
  H_TS_Thread* p_Exit;
  H_TS_Thread* p_next;
  H_TS_Thread* ap_last;
  H_TS_Thread* ap_next;
  H_TS_RunTime CPU_Load_RunningTime;

  for(;;){


    //通过速度比较快的方法判断是否需要处理
    if((H_TS_LL_Core_Instance.WaitAddThreads!=NULL)||(H_TS_LL_Core_Instance.ExitThreads!=NULL)){

      //读取要处理的线程链表 线程可能同时出现在H_TS_Core->WaitAddThreads和H_TS_Core->ExitThreads中 读取要同时读取 并且要先处理p_Add
      //需要保证同步 需要屏蔽调度后再读取(顺便标记为NULL)
      oH_TS_LL_SchedulerSuspend();
      p_Add=H_TS_LL_Core_Instance.WaitAddThreads;
      H_TS_LL_Core_Instance.WaitAddThreads=NULL;
      p_Exit=H_TS_LL_Core_Instance.ExitThreads;
      H_TS_LL_Core_Instance.ExitThreads=NULL;
      oH_TS_LL_ResumeSchedulerAuto();

      //添加线程
      p=p_Add;
      if(p!=NULL){

        //找到最后一个节点
        while((ap_next=p->AllList.Next)!=NULL){
          p=ap_next;
        }

        //将链表添加到头部
        p_next=H_TS_LL_Core_Instance.Threads;
        p_Add->AllList.Last=NULL;
        p->AllList.Next=p_next;
        p_next->AllList.Last=p;
        H_TS_LL_Core_Instance.Threads=p_Add;
      }

      //移除线程
      p=p_Exit;
      while(p!=NULL){
        p_next=p->List.Exit.Next;

        p->Status=vH_TS_Thread_Status_Stop;

        //从总链表中移除
        ap_last=p->AllList.Last;
        ap_next=p->AllList.Next;
        if(ap_last==NULL){
          H_TS_LL_Core_Instance.Threads=ap_next;
        }else{
          ap_last->AllList.Next=ap_next;
        }
        if(ap_next!=NULL){
          ap_next->AllList.Last=ap_last;
        }
        
        p=p_next;
      }

      //尝试释放链表中的线程占用的资源
      p=p_Exit;
      while(p!=NULL){
        p_next=p->List.Exit.Next;

        delete_H_TS_Thread(p);
        
        p=p_next;
      }

    }
    



    if(H_TS_LL_Core_Instance.IdleThreadResume!=0){
      H_TS_LL_Core_Instance.IdleThreadResume=0;
      //检测到线程回到空闲线程

      p=H_TS_LL_Core_Instance.Threads;
      while(p!=NULL){
        p->Stack.MaxUsage=p->Stack.Size-sizeof(void*)*H_TS_LL_ThreadStackGetFreeSize(p->Stack.Address,p->Stack.Size/sizeof(void*));
        p=p->AllList.Next;
      }

      oH_TS_DebugAssert(H_TS_LL_Core_Instance.SubReadyThreads!=NULL,"H_TS:H_TS_IdleProcess():此时 SubReadyThreads不能不为NULL");

    }




#if vH_TS_IsEnableCPULoadCalculate != 0
    //计算各个线程的CPU占用率
    CPU_Load_RunningTime=H_TS_LL_Core_Instance.CPU_Load_RunningTime;
    if(CPU_Load_RunningTime>=vH_TS_CPULoad_T){

      p=H_TS_LL_Core_Instance.Threads;

      while(p!=NULL){
        
        p->CPU_Load=(Hsize)(((Hint64)p->CPU_Load_RunningTime)*1000/CPU_Load_RunningTime);
        p->CPU_Load_RunningTime=0;

        p=p->AllList.Next;
      }

      H_TS_LL_Core_Instance.CPU_Load=1000-H_TS_LL_Core_Instance.IdleThread->CPU_Load;

      H_TS_LL_Core_Instance.CPU_Load_RunningTime=0;
    }
#endif




    IdleProcess=H_TS_LL_Core_Instance.IdleProcess;
    if(IdleProcess!=NULL){
      IdleProcess(v);
    }

  }

}

static void ThreadReturnCallback(int RetVal){
  // H_TS_Thread* thisThread;

  // thisThread=cH_TS_LL_ThisThread(H_TS_LL_Core_Instance);

  //虽然线程通过return返回会转到这里 但其实线程还在运行 只是在执行这里的代码而已
  
  //可以在此截获线程退出信息

  H_TS_ThreadExit(RetVal);//实际上还是要调用线程退出方法
}




void* H_TS_LL_ThreadStackInit(void* volatile* Stack,Hsize StackSize,int (*Code)(void*),void* v){
  void* volatile* StackPtr;

  oH_TS_DebugAssert(StackSize<17,"栈大小至少为17*4字节");

  for(Hsize i=0;i<StackSize;i++){
    Stack[i]=(void*)vH_TS_LL_StackMarkValue;
  }

  StackPtr=&Stack[StackSize-17];
  // StackPtr[0]=(void*)0U;//R4
  // StackPtr[1]=(void*)0U;//R5
  // StackPtr[2]=(void*)0U;//R6
  // StackPtr[3]=(void*)0U;//R7
  // StackPtr[4]=(void*)0U;//R8
  // StackPtr[5]=(void*)0U;//R9
  // StackPtr[6]=(void*)0U;//R10
  // StackPtr[7]=(void*)0U;//R11
  StackPtr[8]=(void*)0xFFFFFFFDU;//LR 退回到线程模式 使用PSP

  StackPtr[9]=v;//R0
  // StackPtr[10]=(void*)0U;//R1
  // StackPtr[11]=(void*)0U;//R2
  // StackPtr[12]=(void*)0U;//R3
  // StackPtr[13]=(void*)0U;//R12

  StackPtr[14]=(void*)ThreadReturnCallback;//LR 当线程使用return返回 跳转到ReturnCallback
  StackPtr[15]=(void*)Code;//PC
  StackPtr[16]=(void*)0x01000000U;//xPSR

  return (void*)StackPtr;
}

int H_TS_LL_Init(void* v,Hsize IdleThreadStackSize){
  void* volatile* Stack;
  Hsize Size;

  TypeCheck();

#if vH_TS_IsEnableCPULoadCalculate != 0
  H_TS_GetDT_LastT=0;
#endif

  H_TS_LL_MemoryInit();
  H_TS_LL_Core_Instance.Memory.Malloc=Malloc;
  H_TS_LL_Core_Instance.Memory.Free=Free;


  H_TS_LL_Core_Instance.CurrentThread=NULL;//NULL还还标记着未启动调度

  H_TS_LL_Core_Instance.SchedulerSuspend=0;
  H_TS_LL_Core_Instance.SysTickSuspend=0;
  H_TS_LL_Core_Instance.SchedulerForISR=0;
  H_TS_LL_Core_Instance.ResumeSchedulerDone=0;


#if vH_TS_IsEnableSimpleTick==0
  H_TS_LL_Core_Instance.MissTickCount=0;
#endif


  H_TS_LL_Core_Instance.SubReadyThreads=NULL;
  H_TS_LL_Core_Instance.SubReadyThreadsHighestPriority=vH_TS_ThreadMaxPriorityValue;

  H_TS_LL_Core_Instance.Block_IRQUnblockThreads=NULL;
  H_TS_LL_Core_Instance.SleepThreadsEvent=0;
  H_TS_LL_Core_Instance.TimeBlock_IRQUnblockThreads=NULL;

  H_TS_LL_Core_Instance.BlockThreads=NULL;
  H_TS_LL_Core_Instance.SleepThreads=NULL;
  H_TS_LL_Core_Instance.TimeBlockThreads=NULL;

  H_TS_LL_Core_Instance.ExitThreads=NULL;
  H_TS_LL_Core_Instance.WaitAddThreads=NULL;
  
  H_TS_LL_Core_Instance.IdleThreadResume=0;
  H_TS_LL_Core_Instance.IdleProcess=(void (*)(void*))NULL;
  
  H_TS_LL_Core_Instance.RunningTick=0;

#if vH_TS_IsEnableCPULoadCalculate != 0
  H_TS_LL_Core_Instance.CPU_Load=0;
  H_TS_LL_Core_Instance.CPU_Load_RunningTime=0;
#else
  H_TS_LL_Core_Instance.CPU_Load=-1;
#endif




  //分配空闲线程需要的内存
  {

    Size=sizeof(H_TS_Thread);
    Size+=(sizeof(void*)*vH_TS_LL_StackPtrAlign-1);
    Size/=(sizeof(void*)*vH_TS_LL_StackPtrAlign);
    Size*=(sizeof(void*)*vH_TS_LL_StackPtrAlign);

    if(IdleThreadStackSize==0){
      IdleThreadStackSize=vH_TS_StackSizeDefault;
    }
    
    IdleThreadStackSize+=((sizeof(void*)*vH_TS_LL_StackPtrAlign)-1);
    IdleThreadStackSize/=(sizeof(void*)*vH_TS_LL_StackPtrAlign);
    IdleThreadStackSize*=(sizeof(void*)*vH_TS_LL_StackPtrAlign);

    H_TS_LL_Core_Instance.IdleThread=H_TS_LL_Core_Instance.Memory.Malloc(Size+IdleThreadStackSize);
    if(H_TS_LL_Core_Instance.IdleThread==NULL){
      return -1;
    }
    Stack=&((void* volatile*)H_TS_LL_Core_Instance.IdleThread)[Size/sizeof(void*)];
    
  }

  //初始化空闲线程
  {
    H_TS_LL_ThreadInitParam ThreadInitParam;

    ThreadInitParam.Priority=vH_TS_ThreadMaxPriorityValue;
    ThreadInitParam.Stack=Stack;
    ThreadInitParam.StackSize=IdleThreadStackSize;
    ThreadInitParam.Code=H_TS_IdleProcess;
    ThreadInitParam.v=v;
    ThreadInitParam.ThreadName="<IDLE_THREAD>";

    H_TS_LL_ThreadInit(H_TS_LL_Core_Instance.IdleThread,&ThreadInitParam);
  }




  //初始化线程列表

  H_TS_LL_Core_Instance.IdleThread->List.Ready.IsSubReady=0;
  H_TS_LL_Core_Instance.IdleThread->List.Ready.Last=NULL;
  H_TS_LL_Core_Instance.IdleThread->List.Ready.Next=NULL;
  H_TS_LL_Core_Instance.ReadyThreads=H_TS_LL_Core_Instance.IdleThread;

  H_TS_LL_Core_Instance.Threads=H_TS_LL_Core_Instance.IdleThread;

  return 0;
}

void H_TS_LL_Start(void (*Callback)(void*),void* v,void (*SetTickCallback)(void (*)(void*),void*)){
  
  //所使用的寄存器在H_TS_LL.h中包含相应的头文件来提供(e.g. 在H_TS_LL.h中添加 #include "stm32h7xx.h" )
  FPU->FPCCR|=FPU_FPCCR_ASPEN_Msk|FPU_FPCCR_LSPEN_Msk;//使能Control自动设置与FPU惰性压栈 在Cortex-M4F M7中可以提升性能
  SCB->SHPR[10]=0xFFU;//设置PendSV优先级为最低 软件中断必须不能打断其他中断
  // HAL_NVIC_SetPriority(PendSV_IRQn,15,0);//设置PendSV优先级为最低 软件中断必须不能打断其他中断

  //线程相关指针配置
  H_TS_LL_ThreadScheduleISR=H_TS_LL_StartFirstThread;//PendSV调用设置为H_TS_LL_StartFirstThread
  H_TS_LL_Core_Instance.CurrentThread=H_TS_LL_Core_Instance.ReadyThreads;

  //设置并启动Tick中断
  SetTickCallback(Callback,v);

  oH_TS_LL_CallScheduleISR();//触发调度中断

  for(;;){}
}

void H_TS_LL_ThreadInit(H_TS_Thread* Thread,const H_TS_LL_ThreadInitParam* ThreadInitParam){
  
  Thread->ContextStackPointer=H_TS_LL_ThreadStackInit(ThreadInitParam->Stack,ThreadInitParam->StackSize/sizeof(void*),ThreadInitParam->Code,ThreadInitParam->v);
  
  Thread->Status=vH_TS_Thread_Status_Ready;
  Thread->IsNotReady=0;

  
  Thread->CPU_Load=-1;
#if vH_TS_IsEnableCPULoadCalculate != 0
  Thread->CPU_Load_RunningTime=0;
#endif

  Thread->Priority=ThreadInitParam->Priority;

#ifdef H_TS_ErrnoPointer
  Thread->Errno=0;
#endif

  Thread->IsIRQUnblock=0;
  Thread->IRQUnblockList.Next=NULL;

  Thread->Stack.Address=ThreadInitParam->Stack;
  Thread->Stack.Size=ThreadInitParam->StackSize;
  Thread->Stack.MaxUsage=ThreadInitParam->StackSize-sizeof(void*)*H_TS_LL_ThreadStackGetFreeSize(ThreadInitParam->Stack,ThreadInitParam->StackSize/sizeof(void*));

  Thread->Monitor=NULL;
  Thread->RetVal=0;

  Thread->ThreadName=ThreadInitParam->ThreadName;

  Thread->AllList.Next=NULL;
  Thread->AllList.Last=NULL;
}




static void* Malloc(Hsize Size){
  void* r;

  r=H_TS_LL_Malloc(Size);
  if(r==NULL){
    H_TS_LL_MemoryErrorCallback();
  }

  return r;
}

static void Free(void* v){
  H_TS_LL_Free(v);
}

static void TypeCheck(){

  oH_TS_DebugAssert(!(
    (sizeof(Hsize)==sizeof(void*))
    &&(sizeof(Husize)==sizeof(void*))
    &&(sizeof(Hfunction)==sizeof(void (*)(void)))
  ),"TypeSizeError");

}



